﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EBookStore.Books;
using EBookStore.Users;
using EBookStore.Payments;

namespace EBookStore.Orders
{
    /// <summary>
    /// Available order statuses
    /// </summary>
    public enum eOrderStatus : short
    {
        /// <summary>
        /// Order created.
        /// </summary>
        Created = 0,

        /// <summary>
        /// Order was charged
        /// </summary>
        Charged = 1, 

        /// <summary>
        /// All books ordered from publishers
        /// </summary>
        AllBooksOrderedFromPublisher =2,

        /// <summary>
        /// All books recieved from publishers
        /// </summary>
        AllBooksRecievedFromPublisher =3,


        /// <summary>
        /// All ordered books are sent
        /// </summary>
        AllBooksSentToCustomer = 4,

        /// <summary>
        /// Canceled by  user
        /// </summary>
        Canceled = 5,

        /// <summary>
        /// Order can not be processed anymore
        /// </summary>
        Closed = 6
    }


    /// <summary>
    /// Each ordered book lifetime statuses
    /// </summary>
    public enum eBookOrderStatus : short
    {
        /// <summary>
        /// was ordered by customer
        /// </summary>
        OrderedByCustomer = 0,

        /// <summary>
        /// ordered from publisher
        /// </summary>
        OrderedFromPublisher = 1,

        /// <summary>
        /// Recieved from publisher
        /// </summary>
        RecievedFromPublisher = 2,

        /// <summary>
        /// Canceled by customer
        /// </summary>
        CanceledByCustomer = 3,

        /// <summary>
        /// Send to customer address
        /// </summary>
        SentToCustomer = 4,

        /// <summary>
        /// Returned by customer
        /// </summary>
        ReturnedByCustomer = 5,

        /// <summary>
        /// Book status is closed, no more processing available
        /// </summary>
        Closed = 6
    }
    

    /// <summary>
    /// Order was made via...
    /// </summary>
    public enum eOrderVia : short
    {
        Phone = 0,
        Email = 1,
        WWW = 2
    }


    /// <summary>
    ///
    /// </summary>
    public class Order
    {


        #region  Properties

        List<OrderStatusHistory> _statusHistory;
        List<SingleBookOrder> _books;

        string _id;
        /// <summary>
        /// Order Uniqe ID
        /// </summary>
        public string ID { get { return _id; } }

        /// <summary>
        /// Customer who made this order
        /// </summary>
        public User User { get { return _user; } }

        /// <summary>
        /// List of ordered books and amount.
        /// </summary>
        public List<SingleBookOrder> BookList 
        {
            get { return _books; }
        }    

        /// <summary>
        /// Order was made via...
        /// </summary>
        public eOrderVia OrderVia { get; set; }

        /// <summary>
        /// Current order status
        /// </summary>
        public eOrderStatus Status
        {
            get { return _statusHistory.Last().Status; }
        }
       
        private Payments.Payment _payment;

        /// <summary>
        /// Order payment.
        /// </summary>
        public Payments.Payment Payment
        {
            get { return _payment; }
           
        }

        /// <summary>
        /// Order's history statutes.
        /// </summary>
        public List<OrderStatusHistory> HistoryStatus
        {
            get { return _statusHistory; }
        }

        #endregion




        #region Events
        
        
        public event EventHandler<OrderStatusEventArgs> OnStatusChange;

        /// <summary>
        /// Order has changed it's status.
        /// </summary>
        private void FireStatusChange(eOrderStatus newStatus)
        {

            EventHandler<OrderStatusEventArgs> status = OnStatusChange;
            if (status != null)
            {
                status(this, new OrderStatusEventArgs(newStatus,this, "Status Change"));
            }
        }



        #endregion

        private User _user = null;


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="User"></param>
        /// <param name="Via"></param>
        public Order(User User, eOrderVia Via, Payments.Payment payment)
        {
            _id = Utils.IDGenerator.CreateUniqeID();
            
            //this._payment = new Payment(payment);
            this._payment = payment;
            _statusHistory = new List<OrderStatusHistory>();
            this.OrderVia = Via;
            _books = new List<SingleBookOrder>();
            _user = User;
            _statusHistory.Add(new OrderStatusHistory(DateTime.Now, eOrderStatus.Created));
        }

        /// <summary>
        /// Add another book to order.
        /// </summary>
        /// <param name="book"></param>
        /// <param name="amount"></param>            
        public void AddBook(Book book, int amount)
        {
            if (amount <= 0)
                throw new Exception("Book amount less then 1");
            if (book.Price <= 0)
                throw new Exception("Book has no price");
            var foundBook = (from b in BookList where b.Book.ISBN.Equals(book.ISBN) select b).FirstOrDefault();
            if (foundBook != null)
            {
                foundBook.Amount += amount;
            }
            else
            {
                SingleBookOrder o = new SingleBookOrder(book, amount);
                BookList.Add(o);
            }            
        }

        /// <summary>
        /// Adds array of books into order
        /// </summary>
        /// <param name="bOrder"></param>
        public void AddBooks(SingleBookOrder[] bOrder)
        {
            foreach (SingleBookOrder b in bOrder)
            {
                AddBook(b.Book, b.Amount);
            }
        }

       
       

        /// <summary>
        /// Updates order status. Status can only be increased
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns>
        public bool UpdateOrderStatus(eOrderStatus status)
        {   
            if ((int)this.Status < (int)status)
            {
                _statusHistory.Add(new OrderStatusHistory(DateTime.Now, status));
                FireStatusChange(status);
                return true;
            }
            else
            {
                throw new Exception("Illegal status!");
            }
        }

        /// <summary>
        /// Counts undelivered books from specific publisher.
        /// </summary>
        /// <param name="pub"></param>
        /// <returns></returns>
        public int CountUndeliveredPublisherBooks(Publishers.Publisher pub)
        {
            return (from el in BookList 
                    where el.Book.PublisherID.Equals(pub.ID) &&
                    (el.Amount - el.SuppliedToCustomer) > 0
                    select (el.Amount - el.SuppliedToCustomer)).Sum();
        }

        

    }
}
